#include "VideoStructs.h"
#include <QDataStream>
#include <QtEndian>
#include <QDebug>
// 序列化VideoMetadata
QByteArray serializeMetadata(const VideoMetadata& metadata) {
    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::BigEndian);

    stream << qToBigEndian(metadata.cameraId)
           << qToBigEndian(metadata.codecId)
           << qToBigEndian(metadata.width)
           << qToBigEndian(metadata.height)
           << qToBigEndian(metadata.timeBaseNum)
           << qToBigEndian(metadata.timeBaseDen);

    // 写入SPS/PPS数据长度和数据
    uint32_t spsSize = metadata.spsPps.size();
    stream << qToBigEndian(spsSize);
    stream.writeRawData(metadata.spsPps.constData(), spsSize);

    return data;
}

// 反序列化VideoMetadata
VideoMetadata deserializeMetadata(const QByteArray& data) {
    VideoMetadata metadata;

    if (data.size() < 24) {
        throw std::runtime_error("元数据太小");
    }

    // 手动解析字节数据
    const quint8* bytes = reinterpret_cast<const quint8*>(data.constData());

    metadata.cameraId = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
    metadata.codecId = (bytes[4] << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7];
    metadata.width = (bytes[8] << 24) | (bytes[9] << 16) | (bytes[10] << 8) | bytes[11];
    metadata.height = (bytes[12] << 24) | (bytes[13] << 16) | (bytes[14] << 8) | bytes[15];
    metadata.timeBaseNum = (bytes[16] << 24) | (bytes[17] << 16) | (bytes[18] << 8) | bytes[19];
    metadata.timeBaseDen = (bytes[20] << 24) | (bytes[21] << 16) | (bytes[22] << 8) | bytes[23];

    qDebug() << "手动解析元数据 - cameraId:" << metadata.cameraId
             << "codecId:" << metadata.codecId
             << "width:" << metadata.width
             << "height:" << metadata.height;

    // 读取SPS/PPS数据
    if (data.size() >= 28) {
        quint32 spsSize = (bytes[24] << 24) | (bytes[25] << 16) | (bytes[26] << 8) | bytes[27];

        if (spsSize > 0 && data.size() >= 28 + spsSize) {
            metadata.spsPps = QByteArray(reinterpret_cast<const char*>(bytes + 28), spsSize);
        }
    }

    return metadata;
}
// 序列化VideoFrame
QByteArray serializeVideoFrame(const VideoFrame& frame) {
    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::BigEndian);

    stream << qToBigEndian(frame.cameraId)
           << qToBigEndian(frame.size)
           << qToBigEndian(frame.pts)
           << qToBigEndian(frame.dts);

    // 写入视频数据
    stream.writeRawData(frame.data.constData(), frame.data.size());

    return data;
}

// 反序列化VideoFrame
VideoFrame deserializeVideoFrame(const QByteArray& data) {
    VideoFrame frame;

    if (data.size() < 24) {
        throw std::runtime_error("帧数据太小");
    }

    // 手动解析字节数据（和元数据一样的方式）
    const quint8* bytes = reinterpret_cast<const quint8*>(data.constData());

    // 手动解析网络字节序
    frame.cameraId = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
    frame.size = (bytes[4] << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7];
    frame.pts = static_cast<qint64>((bytes[8] << 24) | (bytes[9] << 16) | (bytes[10] << 8) | bytes[11]) << 32 |
                (bytes[12] << 24) | (bytes[13] << 16) | (bytes[14] << 8) | bytes[15];
    frame.dts = static_cast<qint64>((bytes[16] << 24) | (bytes[17] << 16) | (bytes[18] << 8) | bytes[19]) << 32 |
                (bytes[20] << 24) | (bytes[21] << 16) | (bytes[22] << 8) | bytes[23];

    qDebug() << "手动解析帧数据 - cameraId:" << frame.cameraId
             << "size:" << frame.size
             << "pts:" << frame.pts
             << "dts:" << frame.dts;

    // 验证字段有效性
    // 允许cameraId=0，因为在VideoMonitorWindow中有相应的处理逻辑
    if (frame.cameraId < 0) {
        throw std::runtime_error("无效的摄像头ID");
    }

    if (frame.size <= 0 || frame.size > 10 * 1024 * 1024) {
        throw std::runtime_error(QString("无效的帧大小: %1").arg(frame.size).toStdString());
    }

    // 检查数据完整性
    if (data.size() < 24 + static_cast<int>(frame.size)) {
        throw std::runtime_error("帧数据不完整");
    }

    // 复制视频数据
    frame.data = QByteArray(reinterpret_cast<const char*>(bytes + 24), frame.size);

    return frame;
}
